<template>
  <div class="generate-position-page">
    <el-row :gutter="20">
      <el-form ref="form" :model="form" size="mini" label-suffix="：">
        <el-col>
          <el-form-item>
            <div class="form-top-wrap">
              <el-select v-model="form.type" placeholder="请选择属性" :disabled="form.isConfirmCode">
                <el-option label="d" value="d" />
                <el-option label="points" value="points" />
              </el-select>
              <el-input v-model="form.width" placeholder="请输入容器宽度" clearable :disabled="form.isConfirmCode"></el-input>
              <el-input v-model="form.height" placeholder="请输入容器高度" clearable :disabled="form.isConfirmCode"></el-input>
              <el-button type="primary" :disabled="form.isConfirmCode" @click="handleConfirmCode">确认输入坐标代码</el-button>
              <el-button @click="handleReset">重新输入</el-button>
            </div>
          </el-form-item>
        </el-col>
        <el-col v-if="form.isConfirmCode">
          <el-form-item label="输出结果1">
            <div class="flex-c-c">
              <el-input type="textarea" :rows="1" v-model="fullOutputCode" readonly></el-input>
              <el-button class="ml-10" type="success" size="mini" @click="copy('fullOutputCode')">复制代码</el-button>
            </div>
          </el-form-item>
        </el-col>
        <el-col v-if="form.isConfirmCode">
          <el-form-item label="输出结果2">
            <div class="flex-c-c">
              <el-input type="textarea" :rows="1" v-model="outputCode" readonly></el-input>
              <el-button class="ml-10" type="success" size="mini" @click="copy('outputCode')">复制代码</el-button>
            </div>
          </el-form-item>
        </el-col>
        <el-col v-if="form.isConfirmCode" class="mb-10">
          <div class="mb-10">
            当前缩放比例：{{ scale / 10 }}
            <el-button type="primary" size="mini" @click="handleScale('down')">缩小</el-button>
            <el-button type="primary" size="mini" @click="handleScale('up')">放大</el-button>
            <el-button type="primary" size="mini" @click="handleRotate">旋转</el-button>
            <el-button size="mini" @click="handleResetAll">重置所有</el-button>
          </div>
          <div v-if="currentPoint" class="mb-10">
            <span
              >当前选中坐标<span>{{ currentPoint.index + 1 }}</span
              >，X：{{ currentPoint.x }}，Y：{{ currentPoint.y }}</span
            >
          </div>
          <div class="svg-container">
            <svg :width="form.width" :height="form.height">
              <g :transform="`translate(${form.width / 2}, ${form.height / 2})`">
                <g>
                  <polyline stroke="yellow" stroke-width="1" :points="`-${2 * form.width} 0 ${2 * form.width} 0`"></polyline>
                  <polyline stroke="yellow" stroke-width="1" :points="`0 -${2 * form.height} 0 ${2 * form.height}`"></polyline>
                </g>
                <g :transform="`scale(${scale / 10}) rotate(${rotate})`">
                  <path v-if="form.type === 'd'" stroke="red" stroke-width="1" :d="form.d"></path>
                  <polyline v-if="form.type === 'points'" stroke="red" stroke-width="1" :points="form.points"></polyline>
                  <circle v-if="currentPoint" :cx="currentPoint.x" :cy="currentPoint.y" r="1" fill="green">
                    <animate attributeName="r" values="0;1;2;3;3;2;1;0" dur="0.5s" begin="0s" repeatCount="indefinite" />
                  </circle>
                </g>
              </g>
            </svg>
          </div>
        </el-col>
        <el-col v-if="form.isConfirmCode" class="mb-10">
          <div class="mb-10">
            实际输出效果图： 宽度：<input :value="resultForm.width" type="range" min="0" max="2000" @input="handleChangeResultFormWidth" />{{ resultForm.width }} 高度：<input
              :value="resultForm.height"
              type="range"
              min="0"
              max="2000"
              @input="handleChangeResultFormHeight"
            />{{ resultForm.height }}
          </div>
          <div class="mb-10">
            当前缩放比例：{{ scale / 10 }}
            <el-button type="primary" size="mini" @click="handleScale('down')">缩小</el-button>
            <el-button type="primary" size="mini" @click="handleScale('up')">放大</el-button>
            <el-button type="primary" size="mini" @click="handleRotate">旋转</el-button>
            <el-button type="primary" size="mini" @click="handleResetResultWidthAndHeight">重置宽高</el-button>
            <el-button size="mini" @click="handleResetAll">重置所有</el-button>
          </div>
          <div v-if="currentPoint" class="mb-10">
            <span
              >当前选中坐标<span>{{ currentPoint.index + 1 }}</span
              >，X：{{ currentPoint.x }}，Y：{{ currentPoint.y }}</span
            >
          </div>
          <div class="svg-container">
            <svg :width="resultForm.width" :height="resultForm.height">
              <g :transform="`translate(${resultForm.width / 2}, ${resultForm.height / 2})`">
                <g>
                  <polyline stroke="yellow" stroke-width="1" :points="`-${2 * resultForm.width} 0 ${2 * resultForm.width} 0`"></polyline>
                  <polyline stroke="yellow" stroke-width="1" :points="`0 -${2 * resultForm.height} 0 ${2 * resultForm.height}`"></polyline>
                </g>
                <g :transform="`scale(${scale / 10}) rotate(${rotate})`">
                  <path v-if="form.type === 'd'" stroke="red" stroke-width="1" :d="resultForm.d"></path>
                  <polyline v-if="form.type === 'points'" stroke="red" stroke-width="1" :points="resultForm.points"></polyline>
                  <circle v-if="currentResultPoint" :cx="currentResultPoint.x" :cy="currentResultPoint.y" r="1"  fill="green">
                    <animate attributeName="r" values="0;1;2;3;3;2;1;0" dur="0.5s" begin="0s" repeatCount="indefinite" />
                  </circle>
                </g>
              </g>
            </svg>
          </div>
        </el-col>
        <el-col :span="3">
          <el-form-item label="坐标代码">
            <el-input v-model="form.originCode" type="textarea" rows="5" placeholder="请输入坐标代码" :disabled="form.isConfirmCode"></el-input>
          </el-form-item>
        </el-col>
        <el-col v-if="form.isConfirmCode" :span="20">
          <div class="position-list-wrap">
            <div class="top-btn-wrap">
              <el-button type="primary" size="mini" @click="handleMXY('XY')">批量-XY</el-button>
              <el-button type="primary" size="mini" @click="handleMXY('X')">批量宽度-X</el-button>
              <el-button type="primary" size="mini" @click="handleMXY('Y')">批量高度-Y</el-button>
              <el-button type="danger" size="mini" @click="handleRXY('XY')">批量取消-XY</el-button>
              <el-button type="danger" size="mini" @click="handleRXY('X')">批量取消宽度-X</el-button>
              <el-button type="danger" size="mini" @click="handleRXY('Y')">批量取消高度-Y</el-button>
              <el-button type="success" size="mini" @click="copy('fullOutputCode')">复制结果1代码</el-button>
              <el-button type="success" size="mini" @click="copy('outputCode')">复制结果2代码</el-button>
            </div>
            <div class="top-input-wrap">
              <el-input v-model="minX" size="mini" placeholder="请输入最小X坐标值" clearable></el-input>
              <el-button type="primary" size="mini" @click="handleMinWidthMX">批量固定宽度-X</el-button>
              <el-input v-model="minY" size="mini" placeholder="请输入最小Y坐标值" clearable></el-input>
              <el-button type="primary" size="mini" @click="handleMinHeightMY">批量固定高度-Y</el-button>
            </div>
            <el-radio-group v-model="currentPointIndex">
              <div v-for="item in points" :key="item.index" class="item">
                <template v-if="item.x && item.y">
                  <el-radio :label="item.index" class="flex-c">
                    <div class="flex-c">
                      <span>坐标{{ item.index + 1 }}，</span>
                      <span>X：</span>
                      <span>{{ item.x }}，</span>
                      <span>Y：</span>
                      <span>{{ item.y }}</span>
                      <div class="btn-wrap">
                        <el-button v-if="!item.mx" size="mini" type="primary" @click="handleMX(item)">宽度-X</el-button>
                        <el-button v-else size="mini" type="danger" @click="handleRX(item)">取消X</el-button>
                        <el-button v-if="!item.my" size="mini" type="primary" @click="handleMY(item)">高度-Y</el-button>
                        <el-button v-else size="mini" type="danger" @click="handleRY(item)">取消Y</el-button>
                      </div>
                      <span>调整后坐标点：</span>
                      <template v-if="item.mx">
                        <span>X：</span>
                        <span>{{ item.mx }}，</span>
                      </template>
                      <template v-if="item.my">
                        <span>Y：</span>
                        <span>{{ item.my }}</span>
                      </template>
                    </div>
                  </el-radio>
                </template>
              </div>
            </el-radio-group>
          </div>
        </el-col>
      </el-form>
    </el-row>
  </div>
</template>
<script>
import BigNumber from "bignumber.js";
export default {
  name: "GeneratePosition",
  data() {
    return {
      form: {
        type: "",
        width: "",
        height: "",
        originCode: "",
        isConfirmCode: false,
      },
      resultForm: {
        width: "",
        height: "",
        d: "",
        points: "",
      },
      currentPointIndex: -1,
      points: [],
      scale: 10,
      rotate: 0,
      minX: "",
      minY: "",
    };
  },
  watch: {
    points: {
      handler() {
        this.handleResultForm();
      },
      deep: true,
    },
  },
  computed: {
    outputCode() {
      const {
        points,
        form: { type },
      } = this;
      let outputCode = "";
      points.forEach((item) => {
        if (type === "d") {
          if ((item.mx && item.my) || (item.x && item.y)) {
            outputCode += `${item.unit}${item.mx || item.x},${item.my || item.y} `;
          } else {
            outputCode += `${item.unit} `;
          }
        } else if (type === "points") {
          outputCode += `${item.mx || item.x} ${item.my || item.y} `;
        }
      });
      return outputCode.trim();
    },
    fullOutputCode() {
      const {
        outputCode,
        form: { type },
      } = this;
      if (type === "d") {
        return `:d="\`${outputCode}\`"`;
      } else if (type === "points") {
        return `:points="\`${outputCode}\`"`;
      }
    },
    currentPoint() {
      const { points, currentPointIndex } = this;
      return points.find((item) => item.index === currentPointIndex);
    },
    currentResultPoint() {
      const { points, currentPointIndex, form, resultForm } = this;
      let { width: formWidth, height: formHeight } = form;
      let { width, height } = resultForm;
      formWidth = new BigNumber(formWidth);
      formHeight = new BigNumber(formHeight);
      const point = points.find((item) => item.index === currentPointIndex);
      if (point) {
        let { x, y, mx, my } = point;
        x && (x = new BigNumber(x));
        y && (y = new BigNumber(y));
        const obj = {
          x: '',
          y: '',
        }
        if (x && mx) {
          obj.x = width - formWidth.minus(x)
        } else if (x) {
          obj.x = x
        }
        if (y && my) {
          obj.y = height - formHeight.minus(y)
        } else if (y) {
          obj.y = y
        }
        return obj;
      }
      return undefined;
    },
  },
  created() {
    const { handleInputPoints } = this;
    const form = localStorage.getItem("datav-generate-position-form");
    if (form) {
      this.form = JSON.parse(form);
      const { width, height } = this.form;
      this.resultForm.width = width;
      this.resultForm.height = height;
      handleInputPoints();
    }
  },
  methods: {
    handleConfirmCode() {
      const { form, handleInputPoints } = this;
      const { type, width, height, originCode } = form;
      if (!type) {
        this.$message.warning("请选择属性");
        return;
      }
      if (!width || !width.trim()) {
        this.$message.warning("请输入容器宽度");
        return;
      }
      if (!height || !height.trim()) {
        this.$message.warning("请输入容器高度");
        return;
      }
      if (!originCode || !originCode.trim()) {
        this.$message.warning("请输入坐标代码");
        return;
      }
      handleInputPoints();
      this.resultForm.width = width;
      this.resultForm.height = height;
      this.form.isConfirmCode = true;
      localStorage.setItem("datav-generate-position-form", JSON.stringify(form));
    },
    handleResultForm() {
      const { form, resultForm, points } = this;
      let { type, width: formWidth, height: formHeight } = form;
      let { width, height } = resultForm;
      formWidth = new BigNumber(formWidth);
      formHeight = new BigNumber(formHeight);
      if (type === "d") {
        let d = "";
        points.map((point) => {
          let { x, y, mx, my, unit } = point;
          width = new BigNumber(width);
          x && (x = new BigNumber(x));
          y && (y = new BigNumber(y));
          d += `${unit}`;
          if (x && mx) {
            d += `${width - formWidth.minus(x)}`;
          } else if (x) {
            d += `${x}`;
          }
          if (y && my) {
            d += `,${height - formHeight.minus(y)}`;
          } else if (y) {
            d += `,${y}`;
          }
          d += " ";
        });
        this.resultForm.d = d.trim();
      } else if (type === "points") {
        let pointsStr = "";
        points.map((point) => {
          let { x, y, mx, my } = point;
          width = new BigNumber(width);
          x && (x = new BigNumber(x));
          y && (y = new BigNumber(y));
          pointsStr += `${mx ? width - formWidth.minus(x) : x} ${my ? height - formHeight.minus(y) : y} `;
        });
        this.resultForm.points = pointsStr.trim();
      }
    },
    handleChangeResultFormWidth(e) {
      const { handleResultForm } = this;
      const { value } = e.target;
      this.resultForm.width = value;
      handleResultForm();
    },
    handleChangeResultFormHeight(e) {
      const { handleResultForm } = this;
      const { value } = e.target;
      this.resultForm.height = value;
      handleResultForm();
    },
    handleInputPoints() {
      let {
        form: { type, originCode },
      } = this;
      originCode = originCode.trim();
      if (type === "d" && originCode.startsWith('d="')) {
        originCode = originCode.replace('d="', "").replace('"', "");
      } else if (type === "points" && originCode.startsWith('points="')) {
        originCode = originCode.replace('points="', "").replace('"', "");
        this.form.points = originCode;
      }
      const arr = originCode.split(" ");
      const points = [];
      if (type === "points") {
        // 两个坐标为一组
        for (let i = 0; i < arr.length; i += 2) {
          const x = arr[i];
          const y = arr[i + 1];
          points.push({
            x,
            y,
            index: i / 2,
            unit: "",
          });
        }
      }
      if (type === "d") {
        arr.map((item, index) => {
          // 替换掉所有字母
          const reg = /[a-zA-Z]/g;
          // 替换掉所有数字和.
          const reg2 = /[0-9.,]/g;
          const code = item.replace(reg, "");
          if (!code) {
            points.push({
              x: "",
              y: "",
              unit: item,
              index,
            });
            return;
          }
          const [x, y] = code.split(",");
          const obj = {
            x,
            y,
            unit: item.replace(reg2, ""),
            index,
          };
          points.push(obj);
        });
        this.form.d = originCode;
      }
      this.points = points;
    },
    handleRotate() {
      this.rotate += 90;
      this.rotate = this.rotate >= 360 ? 0 : this.rotate;
    },
    handleScale(type = "up") {
      this.scale += type === "up" ? 1 : -1;
      this.scale = this.scale < 1 ? 1 : this.scale;
    },
    handleRXY(type = "XY") {
      const { points } = this;
      points.map((item) => {
        if (type === "XY") {
          this.handleRX(item);
          this.handleRY(item);
        }
        if (type === "X") {
          this.handleRX(item);
        }
        if (type === "Y") {
          this.handleRY(item);
        }
      });
    },
    handleRX(item) {
      this.$set(item, "mx", undefined);
    },
    handleRY(item) {
      this.$set(item, "my", undefined);
    },
    handleMXY(type = "XY") {
      const { points } = this;
      points.map((item) => {
        if (type === "XY") {
          this.handleMX(item);
          this.handleMY(item);
        }
        if (type === "X") {
          this.handleMX(item);
        }
        if (type === "Y") {
          this.handleMY(item);
        }
      });
    },
    handleMinWidthMX() {
      const { minX, points } = this;
      if (!minX || !minX.trim()) return this.$message.warning("请先输入最小X坐标值");
      points.map((item) => {
        const { x } = item;
        if (x) {
          x*1 > minX*1 && this.handleMX(item);
        }
      });
    },
    handleMinHeightMY() {
      const { minY, points } = this;
      if (!minY || !minY.trim()) return this.$message.warning("请先输入最小Y坐标值");
      points.map((item) => {
        const { y } = item;
        if (y) {
          y*1 > minY*1 && this.handleMY(item);
        }
      });
    },
    handleMX(item) {
      if (item.x) {
        let { width } = this.form;
        let { x } = item;
        width = new BigNumber(width);
        x = new BigNumber(x);
        const mx = "${width - " + width.minus(x) + "}";
        this.$set(item, "mx", mx);
      }
    },
    handleMY(item) {
      if (item.y) {
        let { height } = this.form;
        let { y } = item;
        height = new BigNumber(height);
        y = new BigNumber(y);
        const my = "${height - " + height.minus(y) + "}";
        this.$set(item, "my", my);
      }
    },
    // 复制操作
    copy(type) {
      // 创建输入框元素
      const input = document.createElement("input");
      // 将想要复制的值
      input.value = this[type];
      // 页面底部追加输入框
      document.body.appendChild(input);
      // 选中输入框
      input.select();
      // 执行浏览器复制命令
      document.execCommand("Copy");
      // 弹出复制成功信息
      this.$message.success("复制成功");
      // 复制后移除输入框
      input.remove();
    },
    handleReset() {
      this.scale = 10;
      this.rotate = 0;
      this.currentPointIndex = -1;
      this.form.isConfirmCode = false;
      this.form.originCode = "";
      this.points = [];
    },
    handleResetResultWidthAndHeight() {
      const { handleResultForm } = this;
      this.$set(this.resultForm, "width", this.form.width);
      this.$set(this.resultForm, "height", this.form.height);
      handleResultForm();
    },
    handleResetAll() {
      this.scale = 10;
      this.rotate = 0;
      this.handleResetResultWidthAndHeight();
    },
  },
};
</script>
<style lang="scss" scoped>
.generate-position-page {
  padding: 20px;
  .form-top-wrap {
    display: flex;
    align-items: center;
    .el-input {
      margin-left: 10px;
    }
    .el-input {
      width: 200px;
      margin-right: 10px;
    }
  }
  .position-list-wrap {
    padding: 20px;
    padding-top: 0;
    margin-bottom: 10px;
    border-radius: 10px;
    border: 1px solid #ebeef5;
    .top-btn-wrap {
      position: sticky;
      top: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      padding-top: 10px;
      padding-bottom: 10px;
      margin: 0 -20px;
      background-color: rgb(189, 166, 166);
      border-top-left-radius: 10px;
      border-top-right-radius: 10px;
      z-index: 1;
    }
    .top-input-wrap {
      position: sticky;
      top: 48px;
      display: flex;
      align-items: center;
      justify-content: center;
      padding-top: 10px;
      padding-bottom: 10px;
      margin: 0 -20px;
      margin-bottom: 10px;
      background-color: rgb(189, 166, 166);
      border-bottom-left-radius: 10px;
      border-bottom-right-radius: 10px;
      z-index: 1;
      .el-input {
        width: 200px;
        margin-left: 10px;
        margin-right: 10px;
      }
    }
    .el-radio-group {
      width: 100%;
      max-height: 400px;
      overflow: auto;
    }
    .item {
      display: flex;
      align-items: center;
      .btn-wrap {
        margin-left: 10px;
        margin-right: 10px;
      }
    }
    .item + .item {
      margin-top: 10px;
    }
  }

  .svg-container {
    background-color: #000;
    padding: 20px;
  }
}
.flex-c-c {
  display: flex;
  align-items: center;
  justify-content: center;
}
.flex-c {
  display: flex;
  align-items: center;
}
.ml-10 {
  margin-left: 10px;
}
.mb-10 {
  margin-bottom: 10px;
}
</style>
